package com.omenkk.juc.AQS;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.locks.StampedLock;
@Slf4j
public class StampedLockDemo {
    private static final StampedLock lock=new StampedLock();
    private static int sharedData = 0;
    private static volatile boolean running = true;

    public static void main(String[] args) {
        //读线程
        Thread readerThread = new Thread(() -> {
            while (running) {
                readDataOptimistically();
                try {
                    Thread.sleep(100); // 读操作间隔
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        });

        //写线程
        Thread writerThread = new Thread(() -> {
            int count = 0;
            while (count < 5) { // 只写5次
                writeData(count);
                count++;
                try {
                    Thread.sleep(500); // 写操作间隔比读长
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
            running = false; // 停止读线程
        });
        readerThread.start();
        writerThread.start();

    }


    //乐观读
    private static void readDataOptimistically() {
        long stamp = lock.tryOptimisticRead();//获取戳
        //先获取值
        long currentData=sharedData;
        //cas校验戳
        if(!lock.validate(stamp)){
            log.debug("戳发生了变化，说明发生了写操作,转为悲观读,尝试获取悲观读锁");
            stamp = lock.readLock();//获取悲观读锁并且更新戳值
            try {
                currentData = sharedData;
            } finally {
                lock.unlockRead(stamp);
            }
        }
        log.debug("线程:{}  读取数据：{}",Thread.currentThread().getName() ,currentData);
        log.debug("当前戳：{}",stamp);
    }

    //写操作
    private static void writeData(int newValue){
        //获取写锁，得到当前戳

        long stamp= lock.writeLock();

        try{
            log.debug("获取写锁，修改数据");
            sharedData=newValue;
            log.debug("修改后数据:{}",sharedData);
        }finally {
            lock.unlock(stamp);
        }
    }
}
